// -*- C++ -*-
#ifndef SDATATYPE_H
#define SDATATYPE_H

namespace sds {

  template <typename T = long, int width = sizeof(T)>
  struct _SIntHelper {
    typedef long Type;
  };

  template <typename T>
  struct _SIntHelper<T, 8> {
    typedef int Type;
  };

  typedef _SIntHelper<>::Type SInteger;

  enum SDataType {
    UCHAR, CHAR, 
    UINT8, INT8, 
    UINT16, INT16, 
    UINT32, INT32, 
    UINT64, INT64, 
    FLOAT32, FLOAT64,
    UNDEFINED
  };

  class SDataTypeConverter {

    friend class SAttribute;
    friend class SDataset;
    friend class SFile;

  private:

    static SDataType convert(SInteger hdfType);
    static SInteger inverse(SDataType type);

  };


  template <typename _Type, SDataType _type, typename _Next> 
  struct SDataTypeListNode { 
    typedef SDataTypeListNode<_Type, _type, _Next> List;

    template <typename __Type, SDataType __type> 
    struct Add : public SDataTypeListNode<__Type, __type, List> {};

    typedef _Type Type;
    static const SDataType type = _type;
    typedef _Next Next;

  };

  struct SDataTypeEmptyList {
    typedef SDataTypeEmptyList List;

    template <typename __Type, SDataType __type> 
    struct Add : public SDataTypeListNode<__Type, __type, List> {};

  };

  
//   typedef SDataTypeEmptyList
//   ::Add<unsigned char, UCHAR>
//   ::Add<signed char, CHAR>
//   ::Add<unsigned char, UINT8>
//   ::Add<signed char, INT8>
//   ::Add<unsigned short, UINT16>
//   ::Add<signed short, INT16>
//   ::Add<unsigned SInteger, UINT32>
//   ::Add<signed SInteger, INT32>
//   ::Add<unsigned SInteger SInteger, UINT64>
//   ::Add<signed SInteger, INT64>
//   ::Add<float, FLOAT32>
//   ::Add<double, FLOAT64>
//   SDataTypeList;

  typedef SDataTypeListNode< 
    unsigned char, UCHAR, SDataTypeListNode<
    signed char, CHAR, SDataTypeListNode<
    unsigned char, UINT8, SDataTypeListNode<
    signed char, INT8, SDataTypeListNode<
    unsigned short, UINT16, SDataTypeListNode<
    signed short, INT16, SDataTypeListNode<
    unsigned long, UINT32, SDataTypeListNode<
    signed long, INT32, SDataTypeListNode<
    unsigned long long, UINT64, SDataTypeListNode<
    signed long long, INT64, SDataTypeListNode<
    float, FLOAT32, SDataTypeListNode<
    double, FLOAT64, SDataTypeEmptyList
    > > > > > > > > > > > > SDataTypeList;

}
#endif
